// ADOAdapter.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "ADOAdapter.h"


#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

static CPool * POOL = NULL;

CADOConnection::CADOConnection(const char * pszConnStr)
: CResource(pszConnStr)
{
  CoInitialize(NULL);

	m_connection.CreateInstance(__uuidof(Connection)); 
	m_connection->CursorLocation = adUseServer; 
	m_connection->Open(pszConnStr, L"", L"", adConnectUnspecified);	

	m_currentlyUsed = true; 
}

CADOConnection::~CADOConnection() 
{ 
  if (NULL == m_connection)
    m_connection->Close();
}

void * CADOConnection::getConnection()
{
  return m_connection;
}

_variant_t CADOConnection::getConnectionVariant() 
{
	return _variant_t((IDispatch*)m_connection, true);
}
_variant_t CADOConnection::getConnectionVariant(_ConnectionPtr con) 
{
	return _variant_t((IDispatch*)con, true);
}

void CADOConnection::setInUse(bool bInUse)
{
  CResource::setInUse(bInUse);

  if (bInUse)
    if (m_connection) m_connection->AddRef();
  else
    if (m_connection) m_connection->Release();
}

CADOPool::CADOPool()
: CPool()
{
	for (int i=0; i<m_initSize; i++)
	{		
		CResource * resource = new CADOConnection(m_pszConnStr);
		resource->setInUse(false);
		m_pool.push_back(resource);		
	}

  m_hMutex = CreateMutex( NULL, TRUE,  "PoolMutex");
}

CADOPool::~CADOPool() 
{
  std::list<CResource*>::iterator ite;	
	for (ite=m_pool.begin(); ite != m_pool.end(); ite++)
	{		
		CResource * resource = *ite;
		resource->setInUse(false);
		delete resource;
	}

  if (NULL != m_hMutex)
    CloseHandle(m_hMutex);
}

CResource* CADOPool::findNewConnection()
{
	bool found = false;
	CResource *entry = NULL;
  std::list<CResource*>::iterator ite;
	ite=m_pool.begin();
	while(ite!=m_pool.end() && !found) {
		entry = *ite;
		if (! entry->getInUse()) {
			entry->setInUse(true);
			found = true;
		}
		ite++;
	}
	if (!found) entry = NULL;
  return entry;
}

CResource* CADOPool::aquire() 
{ 
  WaitForSingleObject(m_hMutex, INFINITE);

	CResource * resource = NULL;
	if (NULL == (resource = findNewConnection())) {
		resource = new CADOConnection(m_pszConnStr);
		m_pool.push_back(resource);
	}

  ReleaseMutex(m_hMutex);

  if (resource) resource->setInUse(true);
	return resource;
}

void CADOPool::release(CResource* res) 
{
  WaitForSingleObject(m_hMutex, INFINITE);

  bool found = false;
  std::list<CResource*>::iterator ite;
	ite=m_pool.begin();

	while(ite!=m_pool.end() && !found) {	
		CResource* entry = *ite;
		if (entry->operator == (*res)) {
			entry->setInUse(false);
			found = true;
		}
		ite++;
	}

  ReleaseMutex(m_hMutex);
}

CPool* CADOPoolFactory::getPool()  
{
  if (NULL == POOL)
    POOL = new CADOPool;
  return POOL;
}


